package com.example.framework509.common.aspects;

import com.example.framework509.common.exceptions.FieldValueException;
import com.example.framework509.common.exceptions.NotExistException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseAutoAspect {

    //service注入需要
    @Autowired
    protected ApplicationContext applicationContext;

    protected <T extends Annotation> T getAnnotation(ProceedingJoinPoint pjp, Class<T> annotationClass){
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        return method.getAnnotation(annotationClass);
    }

    protected Object getFieldValue(Object entity, String fieldName) {
        try {
            Field idField = entity.getClass().getDeclaredField(fieldName);
            idField.setAccessible(true);
            return idField.get(entity);
        }
        catch (IllegalAccessException | NoSuchFieldException e) {
            throw new FieldValueException();
        }
    }

    protected Object getServiceImpl(Object entityParam){
        Class<?> argClass = ((ArrayList) entityParam).get(0).getClass();
        String entityPath = argClass.getName();
        String simpleName = argClass.getSimpleName();
        String servicePath = entityPath.replace("entity", "service.impl")
                .replace(simpleName,simpleName+"ServiceImpl");
        Class<?> serviceClass = null;
        try {
            serviceClass = Class.forName(servicePath);
        } catch (ClassNotFoundException e) {
            throw new NotExistException(servicePath+" not exist");
        }

        Object bean = applicationContext.getBean(serviceClass);
        return bean;
    }

    protected <T extends Annotation> List<String> getFieldsWithAnnotation(Class<T> annotationClass, Object param) {
        List<String> requiredFields = new ArrayList<>();
        Field[] declaredFields = param.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            T requiredFieldAnnotation = field.getDeclaredAnnotation(annotationClass);
            if (requiredFieldAnnotation != null) requiredFields.add(field.getName());
        }
        return requiredFields;
    }

    protected abstract String getOptType();
}
